#pragma once
#include "number.hpp"
#include<unordered_map>
#include<memory>

namespace CAS{

    class 符号{
        protected:
        符号();
        public:
        enum{
            常量类型=0,
            变量类型,
            表达式类型
        };
        virtual int 类型();
        virtual shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数)=0;
        virtual shared_ptr<符号> 导数(const string& 变量)=0;
        virtual shared_ptr<符号> 不定积分(const string& 变量)=0;
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界)=0;

        virtual string 文本(bool 小数形式=false,size_t 保留位数=5)=0;
        virtual ~符号();

        virtual shared_ptr<符号> operator+(shared_ptr<符号> 加数);
        virtual shared_ptr<符号> operator-(shared_ptr<符号> 减数);
        virtual shared_ptr<符号> operator*(shared_ptr<符号> 乘数);
        virtual shared_ptr<符号> operator/(shared_ptr<符号> 除数);
    };

    class 常量:public 符号{
        public:
        实数 值;

        常量(const string& 值);
        常量(const 实数& 值);
        int 类型();

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        shared_ptr<符号> 导数(const string& 变量);
        shared_ptr<符号> 不定积分(const string& 变量);
        shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~常量();

        shared_ptr<符号> operator+(shared_ptr<符号> 加数);
        shared_ptr<符号> operator-(shared_ptr<符号> 减数);
        shared_ptr<符号> operator*(shared_ptr<符号> 乘数);
        shared_ptr<符号> operator/(shared_ptr<符号> 除数);
    };
    class 变量:public 符号{
        public:
        实数 系数;
        string 名称;

        int 类型();
        变量(const 实数& 系数,const string& 名称);

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        virtual shared_ptr<符号> 导数(const string& 变量);
        virtual shared_ptr<符号> 不定积分(const string& 变量);
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~变量();

        shared_ptr<符号> operator+(shared_ptr<符号> 加数);
        shared_ptr<符号> operator-(shared_ptr<符号> 减数);
        shared_ptr<符号> operator*(shared_ptr<符号> 乘数);
        shared_ptr<符号> operator/(shared_ptr<符号> 除数);
    };
    class 导数:public 符号{
        public:
        string 名称;

        导数(const string& 名称);
        ~导数();
        string 文本(bool 小数形式=false,size_t 保留位数=5);
    };

    class 二元符号:public 符号{
        protected:
        shared_ptr<符号> 左,右;
        ~二元符号();
        二元符号(shared_ptr<符号> 左,shared_ptr<符号> 右);
    };

    class 加:public 二元符号{
        public:
        加(符号 *左,符号 *右);

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        virtual shared_ptr<符号> 导数(const string& 变量);
        virtual shared_ptr<符号> 不定积分(const string& 变量);
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~加();
    };

    class 减:public 二元符号{
        public:
        减(符号 *左,符号 *右);

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        virtual shared_ptr<符号> 导数(const string& 变量);
        virtual shared_ptr<符号> 不定积分(const string& 变量);
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~减();
    };

    class 乘:public 二元符号{
        public:
        乘(符号 *左,符号 *右);

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        virtual shared_ptr<符号> 导数(const string& 变量);
        virtual shared_ptr<符号> 不定积分(const string& 变量);
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~乘();
    };

    class 除:public 二元符号{
        public:
        除(符号 *左,符号 *右);

        shared_ptr<符号> 代入(unordered_map<string,shared_ptr<符号>>& 参数);
        virtual shared_ptr<符号> 导数(const string& 变量);
        virtual shared_ptr<符号> 不定积分(const string& 变量);
        virtual shared_ptr<符号> 定积分(const string& 变量,const 实数& 下界,const 实数& 上界);
        string 文本(bool 小数形式=false,size_t 保留位数=5);
        ~除();
    };
}